#pragma once
#include "cmconstants.h"
#include "imagematrix.h"
#include <fstream>


class ImageMatrix;
class Neighborhood2;


/**
 * This Class implements a neighborhood in a matrix.
 * It has a center (located at (CentersRow,CentersCol)), and is usually consist of 9 feature.
 * feature[0] is the value of the cell in the center, feature[1] is the cell at the upper left
 * corner of the center and it rotates clockwise.
 */
class Neighborhood
{
protected:
	//int feature [NEIGHBORHOODSIZE1];				//!< The values of the cells in the neighborhood, a.k.a the features of the instance.
	int* feature;				//!< The values of the cells in the neighborhood, a.k.a the features of the instance.
	unsigned long hash;							//!< Integer one-to-one hash for the feature array.

public:
	virtual void updateHash (void);
	int getFeature (int i) const;				//!< Returns feature[i]
	void setFeature (int i,int val);			//!< Sets feature[i] to val, updates the hash
	void setFeatureLeaveHash (int i, int val);	//!< sets the feature[i] to val, does not update the hash.
	int getHash (void) const;
	virtual void updateFromHash (unsigned long hashValue);

	/** Sets the features to the neighborhood of the given location in the imagematrix.*/
	virtual void updateFromImageMatrix (const ImageMatrix& image, int row, int col);
	
	virtual bool hasSameFeature (const Neighborhood& other) const;
	
	Neighborhood(void);
	
	/**Creates a new object based on the given hash value.*/
	Neighborhood(unsigned long hash);
	
	/**Reads and assigns the values for feature[] from a given array. The size is always NEIGHBORHOOD*/
	Neighborhood(int*);	

	/**Inputs all the data members.*/
	Neighborhood(int* features, int Row, int Col);
	
	Neighborhood(const Neighborhood& other);

	/** Creates a Neighborhood from the neighborhood of a given location in an imagematrix.*/
	Neighborhood(const ImageMatrix& image, int row, int col); 
	
	~Neighborhood(void);

	Neighborhood& operator= (const Neighborhood& other);

	virtual int getSize() const;

	friend std::ostream& operator<<(std::ostream& stream, const Neighborhood& nb);

	friend std::ostream& toStream(std::ostream& stream, const Neighborhood& nb, int nbSize);

	friend void ConvertNB2toNB  (const Neighborhood2& nb2, Neighborhood& nb);
};

